package com.um.jdy.ykc.netty;

import com.um.jdy.ykc.command.YkcCommandFactory;
import com.um.jdy.ykc.utils.RadixsUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.util.ByteProcessor;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;

/**
 * @author 甘天伟
 * @since 2022/7/3
 * 版权所有 广州优匠科技有限公司
 */
@Slf4j
public class YkcDecoder extends LengthFieldBasedFrameDecoder {
    private static final ByteProcessor FIND_HEADER = new ByteProcessor.IndexOfProcessor((byte) 0x68);

    private final int maxFrameLength;
    private final boolean skipWrongData;

    public YkcDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast, boolean skipWrongData) {
        super(ByteOrder.LITTLE_ENDIAN, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
        this.maxFrameLength = maxFrameLength;
        this.skipWrongData = skipWrongData;
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if (skipWrongData) {
            // 查找0x68
            int i = in.forEachByte(FIND_HEADER);
            // 没找到0x68
            if (i == -1) {
                // 缓冲区超过最大长度时清理
                if (in.readableBytes() > maxFrameLength) {
                    byte[] skipBytes = new byte[maxFrameLength];
                    in.readBytes(skipBytes);
                    log.debug("丢弃数据[{}]：{}", ctx.channel().remoteAddress(), RadixsUtil.bytesToHexString(skipBytes));
                }
                return null;
            }
            i = i - in.readerIndex();
            // 找到0x68，丢弃之前的数据
            if (i > 0) {
                byte[] skipBytes = new byte[i];
                in.readBytes(skipBytes);
                log.debug("丢弃数据[{}]：{}", ctx.channel().remoteAddress(), RadixsUtil.bytesToHexString(skipBytes));
            }
        }

        ByteBuf body = (ByteBuf) super.decode(ctx, in);
        if (body == null) {
            return null;
        }

        //读取body
        byte[] bytes = new byte[body.readableBytes()];
        body.readBytes(bytes);
        body.release();
        log.debug("收到数据[{}]：{}", ctx.channel().remoteAddress(), RadixsUtil.bytesToHexString(bytes));

        return YkcCommandFactory.createCommand(bytes);
    }
}
